package com.rslai.base.tool.servertest.command;

import com.rslai.base.tool.servertest.context.Context;
import com.rslai.base.tool.servertest.event.StepNotifier;
import com.rslai.base.tool.servertest.intercept.InterceptorFactory;
import com.rslai.base.tool.servertest.response.Response;

import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class StepCommand {
    protected Logger logger = LoggerFactory.getLogger(getClass());
    InterceptorFactory interceptor = InterceptorFactory.getInstance();
    StepCommand nextCommand;

    public StepCommand getNextCommand() {
        return this.nextCommand;
    }

    public void setNextCommand(StepCommand nextCommand) {
        this.nextCommand = nextCommand;
    }

    public boolean hasNextCommand() {
        return null != this.nextCommand;
    }

    public void execute(Response preResponse, Context context, StepNotifier sNotifier) throws Throwable {
        Response response;
        try {
            this.interceptor.doBefore(this, preResponse, context);
            sNotifier.fireStepStarted(this);
            response = doExecute(preResponse, context);
            sNotifier.fireStepFinished(this);
        } catch (Throwable e) {
            sNotifier.fireStepFailed(this, e);
            throw e;
        }
        this.interceptor.doAfter(this, response, context);
        executeNextCommand(response, context, sNotifier);
    }

    public abstract Response doExecute(Response paramResponse, Context paramContext) throws Throwable;

    public StepCommand cloneCommand() {
        StepCommand command = doClone();
        if ((command != null) && (hasNextCommand())) {
            command.setNextCommand(getNextCommand().cloneCommand());
        }
        return command;
    }

    protected abstract StepCommand doClone();

    protected void executeNextCommand(Response response, Context context, StepNotifier sNotifier) throws Throwable {
        if (hasNextCommand())
            this.nextCommand.execute(response, context, sNotifier);
    }

    public abstract Map<String, Object> toReport();
}